#include "XJ/XJ103_Parser.h"
#include <QDebug>

QList<QByteArray> XJ103_Parser::repairStickyFrame(QByteArray rowRecvBytes)
{
    QList<QByteArray> ret;
    QList<int> headIndexList; // 存储所有的头部位置 90eb的 9在整个接收到的原始帧中下标的位置, 每一个报文都有90eb...90eb...ffff 的头部
    for (int i=0; i< rowRecvBytes.count();  i++)
    {
         if (rowRecvBytes.mid(i,4) == APCI_HEAD && rowRecvBytes.mid(i+12, 4) == APCI_HEAD)
         {
             qDebug() << "发现90eb报文头.";
             qDebug() << "发现头部" << "位置 = " << i;
             headIndexList.push_back(i);
         }
    }

    // 按照报文头的位置进行切分
    if (headIndexList.count() == 2)         // 原始报文数据只有一个103报文
    {
        ret.push_back(rowRecvBytes);
    }
    else if (headIndexList.count() > 2)     // 一帧数据包含夺多个103报文
    {
        // 每两个头部后跟着一帧数据
        QByteArray tmpOneDataPacket;
        for ( int i=0; i<=headIndexList.count()-2; i+=2)
        {
            if ( i == headIndexList.count() -2)
            {
                tmpOneDataPacket = rowRecvBytes.mid(headIndexList[i], -1);
                qDebug() << "最后一段报文" << tmpOneDataPacket;
            }
            else
            {
                tmpOneDataPacket = rowRecvBytes.mid(headIndexList[i], headIndexList[i+2] - headIndexList[i]);
                qDebug() << "临时截取的一个完整的报文数据 = " << tmpOneDataPacket;
            }

            ret.push_back(tmpOneDataPacket);
        }
    }
    qDebug() << "黏包处理结果：" << ret;
    return ret;
}


// 南瑞继保的设备报文包含多个asdu连在一起的情况需要单独做特殊处理
QStringList XJ103_Parser::parserAsdu(QByteArray &packetAsdu, int &type)
{
    QStringList result;

    // 1.将报文传递给 asdu 解析层
    type = m_asduParser.recvPacketTypeFilter(packetAsdu);

    qDebug() << "结束接收报文的分类处理 type = " <<type;

    if ( type == -3)
    {
       qDebug() << "当前需要解析的 asdu = " << packetAsdu;
    }

    // 2. 确认是否收到有用的消息回复
    if( type > -2 )
    {
        qDebug() << "对接收到的消息进行解析处理结果： " ;
        result = m_asduParser.parseBillInfo(type, packetAsdu);
        qDebug() << "parse 结果类型 :  " << type << result;
        qDebug() << "结束接收报文的处理";
    }

    return result;
}

QStringList XJ103_Parser::getBillGroupNames(QStringList &titles, const QString key)
{
    QStringList res;
    foreach (QString it, titles)
    {
        if ( it.contains(key))
        {
            res.append(it);
        }
    }
    qDebug() << "定值相关组：" << res;

    return res;
}

QStringList XJ103_Parser::getBillGroupNoes(QMap<QString,QString> &titles, const QString& key)
{
    QStringList res;        // 返回全部组号
    foreach (QString it, titles.keys())   // map ： 组号-组值
    {
        if (  titles[it].contains(key))
        {
            res.append(it);
        }
    }

    return res;
}

QMap<QString, QString> XJ103_Parser::filteAboutBillGroupNamesNoes(QStringList &groupNames, QStringList &groupNoes, const QString key)
{
    QMap<QString, QString> res;

    // 取出全部的标题
    for (int i=0; i<groupNames.count(); i++)
    {
        if (groupNames.at(i).contains(key))
        {
            res.insert(groupNoes.at(i), groupNames.at(i));
        }
    }

    return res;
}

void XJ103_Parser::parseSFPackets(QByteArray &recvPacket)
{
    // 1. 黏包处理
    QByteArray packetHex = recvPacket.toHex();
    qDebug() <<"开始对四方设备报文进行解析 --- " << packetHex;

    QList<QByteArray> byteArrayList = repairStickyFrame(packetHex);

    // 2. apci 和 asdu 分离, 南瑞继保的103 一帧数据的多个asdu都是响应一个命令的答复，可以直接将一帧的asdu解析结果放到一起
    QStringList results;
    int type;
    for (int i=0; i< byteArrayList.count(); i++)
    {
        QByteArray tmpApci;
        QByteArray tmpAsdu;
        splitApciAsdu(byteArrayList[i], tmpApci, tmpAsdu);
        // 3. 解析 asdu
        QStringList tmpResult =  parserAsdu(tmpAsdu, type);
        if (type != 0 )     // 读组的标题需要一次取到组号和组名两个信息
        {
            results.append(tmpResult);
        }
        else
        {
            m_ginNos.append(tmpResult.mid(0, tmpResult.count()/2));
            m_titleNames.append(tmpResult.mid(tmpResult.count()/2, tmpResult.count()-1));
        }
    }

    // 读取标题，对标题进行过滤，筛选出定值组号
    if ( type==0 )
    {
        m_aboutBillGroupInfoMap = filteAboutBillGroupNamesNoes(m_titleNames, m_ginNos, "定值");

        qDebug() << "-------四方组号信息 :" << m_aboutBillGroupInfoMap;
        results = m_aboutBillGroupInfoMap.keys() + m_aboutBillGroupInfoMap.values();
        emit sig_getTitlesFinished();
    }

    // 4. 将解析结果传给定值展示界面
    //emit sig_parseFinished(results,type);
}


void XJ103_Parser::splitApciAsdu(QByteArray &packet,QByteArray &apci, QByteArray &asdu)
{
    apci = packet.mid(0, LEN_APCI*2);
    asdu = packet.mid(LEN_APCI*2, -1);
    qDebug() << "分离出一个asdu = " << asdu;
}

QList<QStringList> XJ103_Parser::getBillTablesInfo()
{

    QMap<QString, XJ_BillTableStruct> billTablesMap = m_asduParser.getBillTableMap();
    QList<QStringList> ret;
    QStringList nameList;
    QStringList realValueList;
    QStringList defaultValueList;
    QStringList minList;
    QStringList maxList;
    QStringList stepList;
    QStringList unitList;
    QStringList dataTypeList;

    QStringList groupNameList;
    QStringList groupNoList;

    foreach (XJ_BillTableStruct it, billTablesMap)
    {
        qDebug() << "********************* bill table name ***************************";
        qDebug() << it.groupName << "--" << it.groupNo;
        qDebug() << it.billNameList;

        groupNameList.append(it.groupName);
        groupNoList.append(it.groupNo);

        // 将所有的 list 连接起来，中间使用空格隔开
//        nameList.append(it.groupName);
        nameList.append(it.billNameList);

        realValueList.append(it.billRealValueList);

        defaultValueList.append(it.billDefaultValueList);

        minList.append("新的一组最小值:" + it.groupNo);
        minList.append(it.billMinList);

        maxList.append("新的一组最大值:" + it.groupNo);
        maxList.append(it.billMaxList);

        stepList.append("新的一组步长:" + it.groupNo);
        stepList.append(it.billStepsList);

        if (it.billUnitList.isEmpty())              // 南瑞继保读定值组单位，因为本来保护在这组就不存在单位，所有会导致界面展示错误
        {                                           // 使用字符"无"来占位
            int lostUnitNum = it.groupName.count()-2;
            for (int i=0; i<lostUnitNum; i++) {
                it.billUnitList.append("无");
            }
        }

        unitList.push_back("新的一组单位:" + it.groupNo);
        unitList.append(it.billUnitList);

        dataTypeList.append(it.billTypeList);
    }

    ret = {nameList,realValueList,defaultValueList,minList,maxList,stepList,unitList,dataTypeList,groupNoList,groupNameList};

    return  ret;
}

void XJ103_Parser::clearTalbleStructBuffer()
{
    m_asduParser.clearBillTableBuffer();
}

